﻿using UnityEngine;
using System.Collections;
using DateTime = System.DateTime;
using FutureCode.Game.Command;

/// <summary>
/// 骷髅怪行为脚本
/// </summary>
[RequireComponent(typeof(CharacterController))]
public class SkeletonBehaviour : MonoBehaviour, IMoveableObject {
    public static float WanderSpeed = 1.2f;
    public static float PursuitSpeed = 3f;

    /// <summary>
    /// 静态玩家对象
    /// </summary>
    public static GameObject Player;
    /// <summary>
    /// 静态玩家脚本对象
    /// </summary>
    static SoldierBehaviour playerBehaviour;
    /// <summary>
    /// 骷髅角色控制器
    /// </summary>
    public CharacterController Controller;
    /// <summary>
    /// 骷髅怪ID
    /// </summary>
    public int ID;
    /// <summary>
    /// 骷髅生命值，[0, 100]
    /// </summary>
    public int Life = 100;
    /// <summary>
    /// 骷髅最远漫步距离
    /// </summary>
    public float MaxWanderDistance = 5;
    /// <summary>
    /// 骷髅视距
    /// </summary>
    public float SightDistance = 15;
    /// <summary>
    /// 骷髅决策间隔时间(s)，间隔取Random[1f, StrategyMakeInterval]
    /// </summary>
    public float StrategyMakeInterval = 3f;
    /// <summary>
    /// 如果为true，不再执行Update函数内语句
    /// </summary>
    public bool Death = false;
    /// <summary>
    /// 是否在注视状态
    /// </summary>
    public bool Warn { set { anim.warn = value; } }
    //IMoveableObject接口实现属性，方便ShadowBehaviour调用
    public GameObject Object { get { return gameObject; } }
    //IMoveableObject接口实现属性，方便ShadowBehaviour调用
    public Vector3 Position
    {
        get
        {
            return transform.position;
        }
        set
        {
            transform.position = value;
        }
    }
    //IMoveableObject接口实现属性，方便ShadowBehaviour调用
    public Quaternion Rotation
    {
        get
        {
            return transform.rotation;
        }
        set
        {
            transform.rotation = value;
        }
    }

    ShadowBehaviour shadowBehaviour;
    /// <summary>
    /// 攻击是否被打断
    /// </summary>
    bool breakAttack = false;
    /// <summary>
    /// 骷髅动画行为脚本
    /// </summary>
    SkeletonAnimationBehaviour anim;
    /// <summary>
    /// 当前决策状态
    /// </summary>
    Strategy currentStrategy = Strategy.Idle;
    /// <summary>
    /// 射线检测忽略层
    /// </summary>
    int uncastLayerMask;

	void Awake () {
        uncastLayerMask = ~(1 << LayerMask.NameToLayer("BirthPoint"));
        var animator = GetComponent<Animator>();
        anim = animator.GetBehaviour<SkeletonAnimationBehaviour>();
        anim.skeleton_behaviour = this;
        Controller = GetComponent<CharacterController>();
        attackTrigger = transform.FindChild("Sword").GetComponent<BoxCollider>();

        if (Player == null)
            Player = GameObject.FindWithTag("Player");
        if (playerBehaviour == null)
            playerBehaviour = Player.GetComponent<SoldierBehaviour>();

        if (NetManager.Instance.Connected && !GameSettings.Instance.IsPlayerClient)
        {
            GameObject obj = GameObject.Instantiate(ShadowManager.Instance.ShadowPrefab,
                Vector3.zero, Quaternion.identity) as GameObject;
            obj.name = "Shadow_Monster";
            shadowBehaviour = obj.GetComponent<ShadowBehaviour>();
            shadowBehaviour.TriggerSize = new Vector3(2f, 0.1f, 2f);
            shadowBehaviour.OriginObject = this;
            shadowBehaviour.CloseInterval = 0.1f;
            shadowBehaviour.UseSmoothRotation = false;

            shadowBehaviour.AddEventListener(BehaviourType.Attack, () =>
            {
                anim.attack = true;
            });
        }
    }

    void Start()
    {
        uncastLayerMask = ~(1 << LayerMask.NameToLayer("BirthPoint"));
    }

	// Update is called once per frame
	void Update () {
        //如果当前客户端为非玩家客户端，则直接返回
        if (!GameSettings.Instance.IsPlayerClient)
        {
            return;
        }

        if (Death)
        {
            return;
        }

        if(!playerBehaviour.IsLive)
        {
            //如果玩家死亡，则进入空闲状态
            Idle();
            return;
        }

        if (Time.frameCount % 30 == 0)
        {
            if (FindPlayer())
            {
                //如果找到玩家，进入注视状态
                anim.warn = true;

                if (currentStrategy != Strategy.Pursuit)
                {
                    if (CloseTo(Player.transform.position))
                    {
                        //追赶状态下如果靠近玩家，则对玩家发动攻击
                        var targetForward = Player.transform.position - transform.position;
                        transform.forward = targetForward;
                        anim.attack = true;
                    }
                    else
                    {
                        //没有靠近玩家，开始追赶
                        StartCoroutine(PursuitPlayer());
                    }
                }
            }
            else if (currentStrategy == Strategy.Wander)
            {
            }
            else
            {
                //没有找到玩家，进入空闲状态
                Idle();
            }

            if(currentStrategy == Strategy.Idle)
            {
                //如果当前是空闲状态，则开始漫步
                StartCoroutine(Wander());
            }

        }
    }
    void Idle()
    {
        if (currentStrategy == Strategy.Idle)
            return;

        if (GameSettings.Instance.IsPlayerClient)
        {
            //如果当前客户端为玩家客户端，则提交当前空闲状态到服务器
            //由服务器广播给所有客户端
            var cmd = GetCurrentStateCmd(MonsterChangedStateType.Idle);
            NetManager.Instance.Send(cmd);
        }

        anim.speed = 0;
        anim.warn = false;
        anim.attack = false;
        anim.end_locomotion = true;
        currentStrategy = Strategy.Idle;
    }
    /// <summary>
    /// 空闲同步
    /// </summary>
    /// <param name="position">位置</param>
    /// <param name="rotation">旋转</param>
    /// <param name="time">时间</param>
    public void IdleSync(Vector3 position, Quaternion rotation, DateTime time)
    {
        if(GameSettings.Instance.EnableSyncStrategy)
        {
            shadowBehaviour.StopMove(position, rotation);
            anim.speed = 0;
            anim.warn = false;
        }
        else
        {
            transform.position = position;
            transform.rotation = rotation;
            Idle();
        }

    }
    void OnTriggerEnter(Collider other)
    {
        if(!GameSettings.Instance.IsPlayerClient)
        {
            return;
        }
        if (other.tag == "Bullet")
        {
            //如果进入的碰撞提为子弹，则受到伤害
            Injured();
        }
    }
    public void Injured()
    {
        anim.damage = true;
        if (!GameSettings.Instance.IsPlayerClient)
        {
            //如果不是玩家客户端，播放受伤动画后返回。
            return;
        }
        Life -= 20;
        if (Life <= 0)
        {
            //如果生命值小于等于0，则进入死亡状态，提交到服务器进行广播
            var cmd = GetCurrentStateCmd(MonsterChangedStateType.Dead);
            NetManager.Instance.Send(cmd);

            anim.death = true;
            Death = true;

            //根据ID，通过怪物管理器进行销毁当前骷髅对象
            MonsterManager.Instance.DestoryMonster(ID);
            var colliders = transform.GetComponents<Collider>();
            foreach (var c in colliders)
                c.enabled = false;
        }
        else
        {
            //如果生命值大于0，进入受伤状态，提交到服务器进行广播
            var cmd = GetCurrentStateCmd(MonsterChangedStateType.Injured);
            NetManager.Instance.Send(cmd);

            //受到伤害看向玩家
            transform.LookAt(Player.transform);
        }
        //breakAttack设为true，进行打断攻击判断
        breakAttack = true;
    }

    /// <summary>
    /// 查找玩家
    /// </summary>
    /// <returns>是否找到玩家</returns>
    bool FindPlayer()
    {
        var forward = transform.forward;
        var playerPosition = Player.transform.position;
        playerPosition.y += 1;
        var directionToPlayer = playerPosition - transform.position;
        float angle = Vector3.Angle(forward, directionToPlayer);
        //如果骷髅怪朝向与玩家方向超过90度，则无法找到玩家
        if(angle < 90)
        {
            var distance = Vector3.Distance(transform.position, Player.transform.position);
            if (distance > SightDistance)
            {
                //如果与玩家距离超过视距，则无法找到玩家
                return false;
            }
            var start = transform.position;
            start.y += 1;
            Ray ray = new Ray(start, directionToPlayer);
            Debug.DrawRay(transform.position, directionToPlayer);
            RaycastHit hit;
            if(Physics.Raycast(ray, out hit, SightDistance, uncastLayerMask))
            {
                if (hit.collider.tag == "Player")
                {
                    //如果与玩家之间没有障碍物阻挡，则找到玩家
                    return true;
                }
                Debug.LogWarning(hit.collider.name);
            }
        }
        return false;
    }

    /// <summary>
    /// 进行漫步
    /// </summary>
    /// <returns></returns>
    IEnumerator Wander()
    {
        currentStrategy = Strategy.Wander;

        //使用四个方向（前后左右）初始化四个射线
        Ray[] rays = new Ray[4];
        rays[0] = new Ray(transform.position, transform.forward);
        rays[1] = new Ray(transform.position, -transform.forward);
        rays[2] = new Ray(transform.position, -transform.right);
        rays[3] = new Ray(transform.position, transform.right);

        //随机挑选一个方向的射线进行射线检测，判断可以行走的距离
        RaycastHit hit;
        int randomIndex = Random.Range(0, rays.Length - 1);
        Physics.Raycast(rays[randomIndex], out hit, 100f);
        var pos = hit.point;
        float distance = Vector3.Distance(pos, transform.position) -.5f;
        if (distance > MaxWanderDistance)
        {
            distance = MaxWanderDistance;
        }
        //设置朝向为行走方向
        transform.forward = rays[randomIndex].direction.normalized;

        //提交漫步状态到服务器广播
        var cmd = GetCurrentStateCmd(MonsterChangedStateType.StartWander);
        NetManager.Instance.Send(cmd);

        if (distance > 0.5f)
            distance = Random.Range(0.5f, distance);
        var targetPos = transform.position + transform.forward * distance;

        //通知骷髅动画行为脚本开始移动
        anim.speed = WanderSpeed;
        Move();
        while (!CloseTo(targetPos, 2f))
        {
            //未靠近目标位置，继续前行
            if (currentStrategy != Strategy.Wander)
            {
                //若策略改变，则跳出循环
                break;
            }
            yield return new WaitForFixedUpdate();
        }

        if (currentStrategy == Strategy.Wander)
        {
            //提交停止漫游状态到服务器
            cmd = GetCurrentStateCmd(MonsterChangedStateType.EndLocomotion);
            NetManager.Instance.Send(cmd);
            //通知动画脚本停止移动
            StopMove();
            yield return new WaitForSeconds(Random.Range(1f, StrategyMakeInterval));

            if (currentStrategy == Strategy.Wander)
            {
                //重置为空闲状态
                Idle();
            }
        }
    }
    /// <summary>
    /// 追赶玩家
    /// </summary>
    /// <returns></returns>
    IEnumerator PursuitPlayer()
    {
        currentStrategy = Strategy.Pursuit;
        var targetPosition = Player.transform.position;
        transform.LookAt(targetPosition);

        var cmd = GetCurrentStateCmd(MonsterChangedStateType.StartPursuit);
        NetManager.Instance.Send(cmd);

        anim.speed = PursuitSpeed;
        Move();
        while (!CloseTo(targetPosition) && !CloseTo(Player.transform.position))
        {
            yield return new WaitForFixedUpdate();
        }

        cmd = GetCurrentStateCmd(MonsterChangedStateType.Warn);
        NetManager.Instance.Send(cmd);

        StopMove();
        currentStrategy = Strategy.Warn;
        anim.speed = 0;
    }

    /// <summary>
    /// 是否贴近目标
    /// </summary>
    /// <param name="target">目标位置</param>
    /// <param name="distanceIsClose">判断间隔</param>
    /// <returns>是否贴近目标</returns>
    bool CloseTo(Vector3 target, float distanceIsClose = 3)
    {
        distanceIsClose += 0.05f;
        return Vector3.Distance(transform.position, target) <= distanceIsClose;
    }

    /// <summary>
    /// 用于攻击判断的触发器
    /// </summary>
    BoxCollider attackTrigger;
    /// <summary>
    /// 执行攻击
    /// </summary>
    /// <returns></returns>
    IEnumerator attack()
    {
        //重置breakAttack
        breakAttack = false;
        //攻击前奏，1s
        yield return new WaitForSeconds(1);
        if (!breakAttack)
        {
            //若没有被打断攻击，使触发器有效
            attackTrigger.enabled = true;
            //0.5s后使触发器无效，结束攻击
            yield return new WaitForSeconds(0.5f);
            attackTrigger.enabled = false;
        }
    }
    /// <summary>
    /// 攻击
    /// </summary>
    public void Attack()
    {
        if (GameSettings.Instance.IsPlayerClient)
        {
            //若当前客户端为玩家客户端，提交骷髅攻击通知到服务端
            var cmd = GetCurrentStateCmd(MonsterChangedStateType.EndLocomotion);
            NetManager.Instance.Send(cmd);
            cmd = GetCurrentStateCmd(MonsterChangedStateType.Attack);
            NetManager.Instance.Send(cmd);
            //开始攻击
            StartCoroutine(attack());
        }
    }
    /// <summary>
    /// 骷髅死亡
    /// </summary>
    public void Dead()
    {
        Life = 0;
        Death = true;
        anim.death = true;
        if(!GameSettings.Instance.IsPlayerClient)
        {
            GameObject.Destroy(shadowBehaviour.gameObject);
        }
    }
    /// <summary>
    /// 同步-开始移动
    /// </summary>
    /// <param name="startPosition">开始位置</param>
    /// <param name="rotation">开始旋转</param>
    /// <param name="time">开始时间</param>
    /// <param name="speed">移动速度</param>
    public void StartLocomotionSync(Vector3 startPosition, Quaternion rotation, DateTime time, float speed)
    {
        if(GameSettings.Instance.EnableSyncStrategy)
        {
            shadowBehaviour.Move(startPosition, rotation, speed, time, NetManager.Instance.Clock.Now);
        }
        else
        {
            transform.position = startPosition;
            transform.rotation = rotation;
            anim.speed = speed;
            Move();
        }
    }
    /// <summary>
    /// 同步-结束移动
    /// </summary>
    /// <param name="endPosition"></param>
    /// <param name="rotation"></param>
    /// <param name="time"></param>
    public void EndLocomotionSync(Vector3 endPosition, Quaternion rotation, DateTime time)
    {
        if (GameSettings.Instance.EnableSyncStrategy)
        {
            shadowBehaviour.StopMove(endPosition, rotation);
        }
        else
        {
            transform.position = endPosition;
            transform.rotation = rotation;
            anim.speed = 0;
            StopMove();
        }
    }

    /// <summary>
    /// 同步-攻击
    /// </summary>
    /// <param name="attackPosition">攻击位置</param>
    /// <param name="rotation">攻击旋转</param>
    /// <param name="time">攻击时间</param>
    public void AttackSync(Vector3 attackPosition, Quaternion rotation, DateTime time)
    {
        if (GameSettings.Instance.EnableSyncStrategy)
        {
            shadowBehaviour.AddBehaviour(attackPosition, rotation, BehaviourType.Attack);
        }
        else
        {
            StopMove();
            transform.position = attackPosition;
            transform.rotation = rotation;
            anim.attack = true;
        }
    }
    /// <summary>
    /// 获取当前状态命令
    /// </summary>
    /// <param name="type">命令类型</param>
    /// <returns>填充的命令对象</returns>
    public MonsterStateChangedCommand GetCurrentStateCmd(MonsterChangedStateType type)
    {
        MonsterStateChangedCommand cmd = new MonsterStateChangedCommand();
        cmd.MonsterID = this.ID;
        cmd.Life = this.Life;
        cmd.PosX = transform.position.x;
        cmd.PosY = transform.position.y;
        cmd.PosZ = transform.position.z;
        cmd.RotationX = transform.rotation.x;
        cmd.RotationY = transform.rotation.y;
        cmd.RotationZ = transform.rotation.z;
        cmd.RotationW = transform.rotation.w;
        cmd.Time = NetManager.Instance.Clock.Now;
        cmd.ChangedStateType = type;
        return cmd;
    }

    public void SetSpeed(float speed)
    {
        anim.speed = speed;
    }
    /// <summary>
    /// 开始移动
    /// </summary>
    public void Move()
    {
        //if (!GameSettings.Instance.IsPlayerClient)
        //{
        //    //anim.speed = shadowBehaviour.Speed;
        //    anim.speed = WanderSpeed;
        //}
        anim.start_locomotion = true;
        anim.end_locomotion = false;
    }
    /// <summary>
    /// 停止移动
    /// </summary>
    public void StopMove()
    {
        anim.start_locomotion = false;
        anim.end_locomotion = true;
    }
    /// <summary>
    /// 策略枚举
    /// </summary>
    enum Strategy
    {
        Idle,
        Wander,
        Warn,
        Aim,
        Pursuit,
        Attack,
    }
}

